মাল্টি-টেনেন্সি (Multi-Tenancy) হলো একটি অ্যাপ্লিকেশন বা ডাটাবেস আর্কিটেকচার যা একক ইনস্ট্যান্স ব্যবহার করে একাধিক ক্লায়েন্ট বা "টেনেন্ট" (tenant) এর তথ্য সংগ্রহ এবং পরিচালনা করে। স্প্রিং ORM এবং Hibernate ব্যবহার করে মাল্টি-টেনেন্সি বাস্তবায়ন করলে, একাধিক ডাটাবেস বা একক ডাটাবেসে বিভিন্ন টেবিলের মাধ্যমে ডেটা আলাদা করা যায়।
এটি সাধারণত ডাটাবেস পার্টিশনিং (Database Partitioning), টেবিল পার্টিশনিং (Table Partitioning) বা একাধিক ডাটাবেস (Multiple Databases) এর মাধ্যমে করা হয়। মাল্টি-টেনেন্ট কনফিগারেশন বেশিরভাগ ক্ষেত্রে একটি অ্যাপ্লিকেশনে একাধিক টেনেন্টের জন্য আলাদা ডেটা রাখতে ব্যবহৃত হয়, যেমন ক্লাউড ভিত্তিক অ্যাপ্লিকেশন যেখানে বিভিন্ন ক্লায়েন্টের ডেটা পৃথক রাখতে হয়।
প্রথমে একটি DataSource
কনফিগারেশন তৈরি করতে হবে, যা ডাটাবেসের সংযোগ পরিচালনা করবে। এখানে আমরা AbstractRoutingDataSource
ব্যবহার করবো যা ডাটাবেস নির্বাচনের জন্য নির্দিষ্ট কন্টেক্সট অনুসারে ডাইনামিক্যালি ডাটাবেস নির্বাচন করবে।
package com.example.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class MultiTenantDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return TenantContext.getCurrentTenant(); // ডাইনামিক্যালি টেনেন্ট নির্বাচন
}
}
TenantContext
ক্লাসটি থ্রেড-লোকাল কন্টেক্সট ব্যবহার করে বর্তমানে যে টেনেন্ট সক্রিয় রয়েছে সেটি সংরক্ষণ করবে।
package com.example.config;
public class TenantContext {
private static final ThreadLocal<String> currentTenant = new ThreadLocal<>();
public static void setCurrentTenant(String tenant) {
currentTenant.set(tenant);
}
public static String getCurrentTenant() {
return currentTenant.get();
}
public static void clear() {
currentTenant.remove();
}
}
Spring কনফিগারেশন ফাইলে MultiTenantDataSource
কনফিগারেশন এবং টেনেন্টের জন্য ডাটা সোর্স সংজ্ঞায়িত করা হবে।
<bean id="dataSource" class="com.example.config.MultiTenantDataSource">
<property name="targetDataSources">
<map>
<entry key="tenant1" value-ref="tenant1DataSource"/>
<entry key="tenant2" value-ref="tenant2DataSource"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="tenant1DataSource"/>
</bean>
<bean id="tenant1DataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/tenant1_db"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="tenant2DataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/tenant2_db"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
Hibernate SessionFactory
কনফিগারেশন টেনেন্ট ডেটাবেস অনুযায়ী ডাইনামিক্যালি কনফিগার করা হবে।
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.example.model"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
TenantContext
ব্যবহার করে সঠিক টেনেন্ট নির্বাচিত করে তার জন্য ডাটাবেস সংযোগ করা হবে।
package com.example.service;
import com.example.config.TenantContext;
import com.example.dao.UserDao;
import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserDao userDao;
public User getUser(int id, String tenant) {
TenantContext.setCurrentTenant(tenant); // টেনেন্ট নির্বাচিত
return userDao.getUser(id);
}
}
DAO লেয়ারটি SessionFactory
থেকে সেশন নেবে এবং সঠিক ডাটাবেসের সঙ্গে কাজ করবে।
package com.example.dao;
import com.example.model.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
@Autowired
private SessionFactory sessionFactory;
public User getUser(int id) {
Session session = sessionFactory.getCurrentSession();
return session.get(User.class, id);
}
}
কন্ট্রোলার লেয়ারটি UserService
থেকে ডাটা ফেচ করবে এবং টেনেন্টের ভিত্তিতে ডাটাবেস নির্বাচন করবে।
package com.example.controller;
import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/{tenant}/{id}")
public User getUser(@PathVariable String tenant, @PathVariable int id) {
return userService.getUser(id, tenant);
}
}
স্প্রিং ORM এ মাল্টি-টেনেন্ট কনফিগারেশনটি একটি শক্তিশালী পদ্ধতি, যা একাধিক টেনেন্টের ডেটা নিরাপদভাবে এবং পৃথকভাবে পরিচালনা করতে সহায়ক। AbstractRoutingDataSource
ব্যবহার করে ডাটাবেস ডাইনামিক্যালি নির্বাচন করা এবং TenantContext
এর মাধ্যমে টেনেন্টের কন্টেক্সট ট্র্যাক করা হয়। এই কনফিগারেশনের মাধ্যমে একাধিক টেনেন্টের জন্য একটি কনসোলিডেটেড ডেটাবেস স্ট্রাকচার তৈরি করা যায়।
Read more